# !/usr/bin/env python
# encoding: utf-8


"""
  @author: gaogao
  @file: Heater P-V.py
  @time: 2022/3/30 15:51
  @desc:
"""
import time

from math import *
from ATS.hardwarescan import conf_file_manager
from ATS.application.LCR_App.U2722A_App import U2722A_App
from ATS.application.LCR_App.B2901BL_App import B2901BLApp
from ATS.application.LASER_App.L8164B_App import L8164B_App
from ATS.application.LASER_App.N7744C_App import N7744C_App
from ATS.datamanager import data_transfer_station as DataTransferStation
from utils.read_ini_2_dict import get_option_value, get_refrence_data, get_loss_data
from utils.get_wave_power_util import get_wave_power_value, get_wave_loss_gc
from ATS.application.VNA_App.N5225B_App import N5225BApp
from ATS.util.calcu_step_util import get_points_list, get_step_list
from ATS.util.save_data_2_csv_util import saveData2CSV
from utils.find3db_util import find3db_util
from collections import namedtuple
from matplotlib import pyplot as plt
import numpy as np
from ATS.switchdriver.LightSwitchDriver import LightSwitchDriver

global half_slope_voltage


# 通道1设置扫描电压，通道2、3固定电压
def pv_test(para_list):
    try:
        result_data = namedtuple("result_data", "subdie,test_item,test_result")
        half_slope_voltage = get_option_value(option="half_slope_voltage")
        vppd = 0.25
        total_time = 20
        if not half_slope_voltage:
            half_slope_voltage = 0.95
        else:
            half_slope_voltage = float(half_slope_voltage)
        try:
            inst_light = LightSwitchDriver.instance()
            if inst_light.is_connected:
                inst_light.set_all_switch("01", "05")
                time.sleep(1)
                print(inst_light.query_switch())
            else:
                inst_light.connect()
            for smu_setting in para_list.smu_setting:
                if smu_setting["mode"] == "sweep":
                    sweep_inst = U2722A_App(smu_setting["smu"])
                    sweep_channel = smu_setting["channel"]
                    sweep_list = smu_setting["voltage_list"]
                    sweep_voltage_range = smu_setting["voltage_range"]
                    sweep_nplc = smu_setting["nplc"]
                    sweep_current_range = smu_setting["current_range"]
                    sweep_current_limit = smu_setting["current_limit"]
                    sweep_inst.output_state(0, sweep_channel)

            l8164 = para_list.l8164_setting
            n7744 = para_list.n7744_setting
            l8164b_app = L8164B_App(l8164["title"])
            n7744c_app = N7744C_App(n7744["title"])

            l8164b_app.set_power_unit()
            l8164b_app.set_power_value(float(l8164["power_value"]))
            l8164b_app.set_wave_length(int(l8164["wave_length"][0]))
            time.sleep(4)
            p_in = l8164b_app.fetch_input_power()
            l8164b_app.output_on()
            n7744c_app.reset()
            n7744c_app.set_power_wave_length()
            n7744c_app.set_power_unit()
            n7744c_app.set_power_range(n7744["power_range"])
            n7744c_app.set_power_atim(n7744["atim"])
            time.sleep(5)

            sweep_inst.set_voltage_range(sweep_channel)
            sweep_inst.set_current_range_limit(sweep_current_range, sweep_current_limit, sweep_channel)
            sweep_inst.output_state(1, sweep_channel)
            wave_power_tuple = get_refrence_data()
            loss_gc = get_wave_loss_gc(l8164["wave_length"][0], get_loss_data())
            loss_sys = get_wave_power_value(l8164["wave_length"][0], wave_power_tuple)
            print("p_in", p_in)
            print("loss_sys", loss_sys)
            print("loss_gc", loss_gc)
            # 设置bias电压
            sweep_inst.set_voltage(half_slope_voltage, sweep_channel)
            sweep_inst.set_voltage_range(2)
            sweep_inst.set_voltage(2 + 0.25 * vppd, 2)
            sweep_inst.set_current_range_limit("120mA", 0.12, 2)
            sweep_inst.output_state(1, 2)

            sweep_inst.set_voltage_range(3)
            sweep_inst.set_voltage(2 - 0.25 * vppd, 3)
            sweep_inst.set_current_range_limit("120mA", 0.12, 3)
            sweep_inst.output_state(1, 3)
            p1_list = []
            for i in range(total_time):
                p1 = n7744c_app.get_power_value()
                p1_list.append(float(p1))
                time.sleep(0.1)
            print("p1", p1_list)
            min_p1 = min(p1_list)
            max_p1 = max(p1_list)

            p1_list.remove(min_p1)
            p1_list.remove(max_p1)

            p1 = sum(p1_list) / len(p1_list)

            sweep_inst.set_voltage(2 - 0.25 * vppd, 2)
            sweep_inst.set_voltage(2 + 0.25 * vppd, 3)
            p2_list = []
            for i in range(total_time):
                p2 = n7744c_app.get_power_value()
                p2_list.append(float(p2))
                time.sleep(0.1)
            print("p2", p2_list)
            min_p2 = min(p2_list)
            max_p2 = max(p2_list)
            print("min_p1", min_p1)
            print("max_p1", max_p1)
            print("min_p2", min_p2)
            print("max_p2", max_p2)
            p2_list.remove(min_p2)
            p2_list.remove(max_p2)
            print("p1_List", p1_list)
            print("p2_list", p2_list)
            p2 = sum(p2_list) / len(p2_list)
            print("p1", p1)
            print("p2", p2)
            er = abs(float(p1) - float(p2))
            print("er", er)

            sweep_inst.output_state(0, sweep_channel)
            sweep_inst.output_state(0, 2)
            sweep_inst.output_state(0, 3)

        except Exception as e:
            print("eee", e)
    except Exception as e:
        print("error", e)


def plot_curve2(curve_list, title, x, y, max_x, max_y):
    color = ["r", "m", "c", "y"]
    label = ["0s", "60s", "300s", "10s"]
    plt.figure(figsize=(20, 20), dpi=100)
    fig, ax = plt.subplots()
    ax.set_title(f"{title} P-V curve")
    for i in range(len(curve_list)):
        ax.plot(curve_list[i][0], curve_list[i][1], color[i], label=f"{label[i]}")
        ax.plot([max_x], [max_y], "s")
        ax.text(max_x, max_y, f"{str(max_x)},{str(max_y)}")
        ax.plot([x], [y], "s")
        ax.text(x, y, f"{str(x)},{str(y)}")
        ax.set_xlabel("Voltage")
        ax.set_ylabel("Power")
        ax.grid(True)
        ax.legend()
    plt.savefig(f"{title}.png")
    plt.show()


def plot_curve(curve_list):
    plt.figure(figsize=(20, 20), dpi=100)
    fig, ax = plt.subplots()
    ax.plot(curve_list[0], curve_list[1], "y")
    ax.grid(True)
    plt.show()


def cal_slope(x, y):
    slope, intercept = np.polyfit(x, y, 1)
    return slope


def find3db(x_data, y_data):
    max_peak = ""
    peak_index = ""
    min_peak = min(y_data)
    peak_index = y_data.index(min_peak)
    length = len(y_data)
    compare_value = float(min_peak) + 3
    min_x = x_data[peak_index]
    target_x_value, target_y_value = "", ""
    index1 = 0
    for i in range(length):
        result = y_data[i] - compare_value
        if 0 < abs(result) < 0.4:
            if (cal_slope([x_data[i], x_data[i + 1]], [y_data[i], y_data[i + 1]])) < 0:
                target_x_value, target_y_value = x_data[i], y_data[i]
                break
            else:
                continue

    if all([target_x_value, target_y_value, min_x, min_peak]):
        return target_x_value, target_y_value, min_x, min_peak


pv_test(locals()['para'])

# n5225bapp = N5225BApp("VNA")
# n5225bapp.start_trigger()
# time.sleep(30)
# print(lca_test(n5225bapp))
# print(n5225bapp.get_snp_data())

# title = "demo"
# curve_list = []
# for i in [0]:
#     x_data, y_data = pv_test(locals()['para'])
#     curve_list.append([x_data, y_data])
#     plot_curve(curve_list)
#     datas = find3db(curve_list[0][0], curve_list[0][1])
#     if datas and len(datas) == 4:
#         print(datas)
#         plot_curve2(curve_list, title, datas[0], datas[1], datas[2], datas[3])
#         saveData2CSV(f"{title}.csv", ["Voltage(V)", "Power(dbm)"], curve_list)
#     else:
#         print("it is error")
